home *** CD-ROM | disk | FTP | other *** search
- ////////////////////////////////////////////////////////////////
- // 1998 Microsoft Systems Journal.
- // from DiLascia Coolmenu\MBTest\CoolMenu.cpp
- //
- #include "StdAfx.h"
- #include "CoolMenu.h"
- #include "Resource.h"
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
-
- // helpers -----------------------------------------------------------------------
- void PLFillRect(CDC& dc, const CRect& rc, COLORREF color);
- void PLDrawEmbossed(CDC& dc, CImageList& il, int i, CPoint p, BOOL bColor=FALSE);
- ////////////////////////////////////////////////////////////////
- // Helper functions
-
- //
- void PLFillRect(CDC& dc, const CRect& rc, COLORREF color)
- {
- CBrush brush(color);
- CBrush* pOldBrush = dc.SelectObject(&brush);
- dc.PatBlt(rc.left, rc.top, rc.Width(), rc.Height(), PATCOPY);
- dc.SelectObject(pOldBrush);
- }
-
- // This is the magic ROP code used to generate the embossed look for
- // a disabled button. It's listed in Appendix F of the Win32 Programmer's
- // Reference as PSDPxax (!) which is a cryptic reverse-polish notation for
- //
- // ((Destination XOR Pattern) AND Source) XOR Pattern
- //
- // which I leave to you to figure out. In the case where I apply it,
- // Source is a monochrome bitmap which I want to draw in such a way that
- // the black pixels get transformed to the brush color and the white pixels
- // draw transparently--i.e. leave the Destination alone.
- //
- // black ==> Pattern (brush)
- // white ==> Destintation (ie, transparent)
- //
- // 0xb8074a is the ROP code that does this. For more info, see Charles
- // Petzold, _Programming Windows_, 2nd Edition, p 622-624.
- //
- #define TRANSPARENTROP 0xb8074a
-
- //////////////////
- // Draw an image with the embossed (disabled) look.
- //
- // dc device context to draw in
- // il image list containing image
- // i index of image to draw
- // p point in dc to draw image at
- // bColor do color embossing. Default is B/W.
- //
- void PLDrawEmbossed(CDC& dc, CImageList& il, int i,
- CPoint p, BOOL bColor)
- {
- IMAGEINFO info;
- VERIFY(il.GetImageInfo(0, &info));
- CRect rc = info.rcImage;
- int cx = rc.Width();
- int cy = rc.Height();
-
- // create memory dc
- CDC memdc;
- memdc.CreateCompatibleDC(&dc);
-
- // create mono or color bitmap
- CBitmap bm;
- if (bColor)
- bm.CreateCompatibleBitmap(&dc, cx, cy);
- else
- bm.CreateBitmap(cx, cy, 1, 1, NULL);
-
- // draw image into memory DC--fill BG white first
- CBitmap* pOldBitmap = memdc.SelectObject(&bm);
- memdc.PatBlt(0, 0, cx, cy, WHITENESS);
- il.Draw(&memdc, i, CPoint(0,0), ILD_TRANSPARENT);
-
- // This seems to be required. Why, I don't know. ???
- COLORREF colorOldBG = dc.SetBkColor(RGB(255,255,255)); // white
-
- // Draw using hilite offset by (1,1), then shadow
- CBrush brShadow(GetSysColor(COLOR_3DSHADOW));
- CBrush brHilite(GetSysColor(COLOR_3DHIGHLIGHT));
- CBrush* pOldBrush = dc.SelectObject(&brHilite);
- dc.BitBlt(p.x+1, p.y+1, cx, cy, &memdc, 0, 0, TRANSPARENTROP);
- dc.SelectObject(&brShadow);
- dc.BitBlt(p.x, p.y, cx, cy, &memdc, 0, 0, TRANSPARENTROP);
- dc.SelectObject(pOldBrush);
- dc.SetBkColor(colorOldBG); // restore
- memdc.SelectObject(pOldBitmap); // ...
- }
-
-
- // constants used for drawing-----------------------------------------------------------------------
- const CXGAP = 1; // num pixels between button and text
- const CXTEXTMARGIN = 2; // num pixels after hilite to start text
- const CXBUTTONMARGIN = 2; // num pixels wider button is than bitmap
- const CYBUTTONMARGIN = 2; // ditto for height
-
- // DrawText flags
- const DT_MYSTANDARD = DT_SINGLELINE|DT_LEFT|DT_VCENTER;
-
- // identifies owner-draw data as mine
- const LONG MYITEMIDM = MAKELONG(MAKEWORD('m','i'),MAKEWORD('m','0'));
- const LONG MYITEMIDD = MAKELONG(MAKEWORD('m','i'),MAKEWORD('d','0'));
-
- // private struct: one of these for each owner-draw menu item
- struct CMyItemData {
- long magicNum; // magic number identifying me
- CString text; // item text
- UINT fType; // original item type flags
- int iButton; // index of button image in image list
- CMyItemData() { magicNum = MYITEMIDM; }
- BOOL IsMyItemData() { return magicNum == MYITEMIDM; }
- };
-
- // private struct: one of these for dropdown buttons WM_NOTIFY
- struct CMyDropData {
- UINT idMenu; // idr popup menu
- UINT uFlags; // default TPM_RIGHTBUTTON
- long magicNum; // magic number identifying me
- CMyDropData() { magicNum = MYITEMIDD; }
- BOOL IsMyDropData() { return magicNum == MYITEMIDD; }
- };
-
-
-
-
- IMPLEMENT_DYNAMIC(CCoolMenuManager, CSubclassWnd)
-
- CCoolMenuManager::CCoolMenuManager()
- {
- m_szButton =CSize(18,18); // will compute later
- }
-
- CCoolMenuManager::~CCoolMenuManager()
- {
- Destroy();
- }
-
- //////////////////
- // Destroy everything. Called from destructor
- //
- void CCoolMenuManager::Destroy()
- {
- m_fontMenu.DeleteObject();
- //TRACE0("ConvertMenuRemove \n");
- while (!m_menuItems.IsEmpty())
- {
- CMyItemData *pmd = (CMyItemData *)m_menuItems.RemoveHead();
- // TRACE1("delete = %s \n",pmd->text);
- delete pmd;
- }
-
- // iterating all (key, value) pairs
- POSITION pos = m_dropButns.GetStartPosition();
- while (pos!=NULL)
- {
- CMyDropData *pdd;
- WORD wKey;
- m_dropButns.GetNextAssoc(pos, wKey, (void *&)pdd);
- delete pdd;
- // TRACE1("id=%d \n",wKey);
- }
-
- m_dropButns.RemoveAll();
- }
-
- //////////////////
- // Call this to install the menu manager. Install(NULL) to un-install.
- //
- void CCoolMenuManager::Install(CFrameWnd* pFrame, CToolBar *pToolBar)
- {
- ASSERT_VALID(pFrame);
- m_pFrame = pFrame;
- m_pToolBar = pToolBar;
-
-
- AddDropDown(ID_FILE_OPEN, IDR_FILEDROPDOWN, TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_VERTICAL);
- HookWindow(pFrame); // install message hook
- }
-
-
- //////////////////
- // Call this to add drop down style buttons
- //
-
- void CCoolMenuManager::AddDropDown(UINT idButton, UINT idMenu, UINT uFlags)
- {
- m_pToolBar->GetToolBarCtrl().SetExtendedStyle(TBSTYLE_EX_DRAWDDARROWS);
-
- TBBUTTONINFO tbi;
- tbi.dwMask= TBIF_STYLE;
- tbi.cbSize= sizeof(TBBUTTONINFO);
- m_pToolBar->GetToolBarCtrl().GetButtonInfo(idButton, &tbi);
- tbi.fsStyle |= TBSTYLE_DROPDOWN;
- m_pToolBar->GetToolBarCtrl().SetButtonInfo(idButton, &tbi);
-
-
- CMyDropData *pdd;
- pdd = new CMyDropData; // create one
- pdd->idMenu = idMenu;
- pdd->uFlags = uFlags;
-
- m_dropButns.SetAt(idButton, pdd);
- }
-
-
- /////////////////////////////////////////////////////////////////////////////////////
- //////////////////
- // Get menu font, creating if needed
- //
- CFont* CCoolMenuManager::GetMenuFont()
- {
- if (!(HFONT)m_fontMenu) {
- NONCLIENTMETRICS info;
- info.cbSize = sizeof(info);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(info), &info, 0);
- VERIFY(m_fontMenu.CreateFontIndirect(&info.lfMenuFont));
- }
- return &m_fontMenu;
- }
-
- // Helper function to draw justified menu text. If the text contains a TAB,
- // draw everything after the tab right-aligned
- //
- void CCoolMenuManager::DrawMenuText(CDC& dc, CRect rc, CString text,
- COLORREF color)
- {
- CString left = text;
- CString right;
- int iTabPos = left.Find('\t');
- if (iTabPos >= 0) {
- right = left.Right(left.GetLength() - iTabPos - 1);
- left = left.Left(iTabPos);
- }
- dc.SetTextColor(color);
- dc.DrawText(left, &rc, DT_MYSTANDARD);
- if (iTabPos > 0)
- dc.DrawText(right, &rc, DT_MYSTANDARD|DT_RIGHT);
- }
-
- #ifndef OBM_CHECK
- #define OBM_CHECK 32760 // from winuser.h
- #endif
-
- //////////////////
- // Draw 3D checkmark
- //
- // dc device context to draw in
- // rc rectangle to center bitmap in
- // bSelected TRUE if button is also selected
- // hbmCheck Checkmark bitmap to use, or NULL for default
- //
- BOOL CCoolMenuManager::Draw3DCheckmark(CDC& dc, const CRect& rc,
- BOOL bSelected, HBITMAP hbmCheck)
- {
- // get checkmark bitmap if none, use Windows standard
- if (!hbmCheck) {
- CBitmap bm;
- VERIFY(bm.LoadOEMBitmap(OBM_CHECK));
- hbmCheck = (HBITMAP)bm.Detach();
- ASSERT(hbmCheck);
- }
-
- // center bitmap in caller's rectangle
- BITMAP bm;
- ::GetObject(hbmCheck, sizeof(bm), &bm);
- int cx = bm.bmWidth;
- int cy = bm.bmHeight;
- CRect rcDest = rc;
- CPoint p(0,0);
- CSize delta(CPoint((rc.Width() - cx)/2, (rc.Height() - cy)/2));
- if (rc.Width() > cx)
- rcDest = CRect(rc.TopLeft() + delta, CSize(cx, cy));
- else
- p -= delta;
-
- // select checkmark into memory DC
- CDC memdc;
- memdc.CreateCompatibleDC(&dc);
- HBITMAP hOldBM = (HBITMAP)::SelectObject(memdc, hbmCheck);
-
- // set BG color based on selected state
- COLORREF colorOld =
- dc.SetBkColor(GetSysColor(bSelected ? COLOR_MENU : COLOR_3DLIGHT));
- dc.BitBlt(rcDest.left, rcDest.top, rcDest.Width(), rcDest.Height(),
- &memdc, p.x, p.y, SRCCOPY);
- dc.SetBkColor(colorOld);
-
- ::SelectObject(memdc, hOldBM); // restore
-
- // draw pushed-in hilight.
- if (rc.Width() > cx) // if room:
- rcDest.InflateRect(1,1); // inflate checkmark by one pixel all around
- dc.DrawEdge(&rcDest, BDR_SUNKENOUTER, BF_RECT);
-
- return TRUE;
- }
-
- //////////////////
- // Draw button form toolbar
- //
- // dc device context to draw in
- // iButton number in m_wndToolBar
- // p start point
- // bEnabled TRUE if button is not disabled
- //
- void CCoolMenuManager::DrawButton(CDC& dc, int iButton, CPoint p, BOOL bEnabled)
- {
- TBBUTTON butn;
- if (m_pToolBar->GetToolBarCtrl().GetButton(iButton, &butn))
- {
- CImageList *ImageList = m_pToolBar->GetToolBarCtrl().GetImageList();
- if (bEnabled)
- ImageList->Draw(&dc, butn.iBitmap, p, ILD_TRANSPARENT);
- else
- {
-
- HICON hIcon = ImageList->ExtractIcon(butn.iBitmap);
- ASSERT(hIcon);
- dc.DrawState(p, CSize(0,0), hIcon, DSS_DISABLED, (HBRUSH)NULL);
- DestroyIcon(hIcon);
-
- // or use DrawEmbossed to draw disabeld button, w/color flag
- // PLDrawEmbossed(dc, *ImageList, butn.iBitmap, p, true);
- }
-
- }
- }
-
-
- //-----------------------------------------------------------------------------------
- //////////////////
- // Handle WM_MEASUREITEM on behalf of frame: compute menu item size.
- //
- BOOL CCoolMenuManager::OnMeasureItem(LPMEASUREITEMSTRUCT lpms)
- {
- ASSERT(lpms);
- CMyItemData* pmd = (CMyItemData*)lpms->itemData;
- ASSERT(pmd);
-
- if (lpms->CtlType != ODT_MENU || !pmd->IsMyItemData())
- return FALSE; // not handled by me
-
- if (pmd->fType & MFT_SEPARATOR)
- {
- // separator: use half system height and zero width
- lpms->itemHeight = GetSystemMetrics(SM_CYMENU)>>1;
- lpms->itemWidth = 0;
-
- } else
- {
-
- // compute size of text: use DrawText with DT_CALCRECT
- CString text = pmd->text;
-
- CWindowDC dc(NULL); // screen DC--I won't actually draw on it
- CRect rcText(0,0,0,0);
- CFont* pOldFont = dc.SelectObject(GetMenuFont());
- dc.DrawText(text, rcText, DT_MYSTANDARD|DT_CALCRECT);
- dc.SelectObject(pOldFont);
-
- // height of item is just height of a standard menu item
- lpms->itemHeight= max(GetSystemMetrics(SM_CYMENU), rcText.Height());
-
- // width is width of text plus a bunch of stuff
- int cx = rcText.Width(); // text width
- cx += CXTEXTMARGIN<<1; // L/R margin for readability
- cx += CXGAP; // space between button and menu text
- cx += m_szButton.cx<<1; // button width (L=button; R=empty margin)
- // whatever value I return in lpms->itemWidth, Windows will add the
- // width of a menu checkmark, so I must subtract to defeat Windows. Argh.
- //
- cx -= GetSystemMetrics(SM_CXMENUCHECK)-1;
- lpms->itemWidth = cx; // done deal
-
- //TRACE1(_T("OnMeasureItem for '%s':"), text); TRACE2(_T("\tw=%d h=%d\n"), lpms->itemWidth, lpms->itemHeight);
- }
- return TRUE;
- }
-
- /////////////////
- // Handle WM_DRAWITEM on behalf of frame. Note: in all that goes
- // below, can't assume rcItem.left=0 because of multi-column menus!
- //
- BOOL CCoolMenuManager::OnDrawItem(LPDRAWITEMSTRUCT lpds)
- {
-
- ASSERT(lpds);
- CMyItemData* pmd = (CMyItemData*)lpds->itemData;
- ASSERT(pmd);
- if (lpds->CtlType != ODT_MENU || !pmd->IsMyItemData())
- return FALSE; // not handled by me
-
- ASSERT(lpds->itemAction != ODA_FOCUS);
- ASSERT(lpds->hDC);
- CDC dc;
- dc.Attach(lpds->hDC);
-
- const CRect& rcItem = lpds->rcItem;
-
- if (pmd->fType & MFT_SEPARATOR)
- {
- // draw separator
- CRect rc = rcItem; // copy rect
- rc.top += rc.Height()>>1; // vertical center
- dc.DrawEdge(&rc, EDGE_ETCHED, BF_TOP); // draw separator line
-
- } else
- { // not a separator
- CString text = pmd->text;
-
- BOOL bDisabled = lpds->itemState & ODS_GRAYED;
- BOOL bSelected = lpds->itemState & ODS_SELECTED;
- BOOL bChecked = lpds->itemState & ODS_CHECKED;
- BOOL bHaveButn=FALSE;
- // Paint button, or blank if none
- CRect rcButn(rcItem.TopLeft(), m_szButton); // button rect
- rcButn += CPoint(0, // center vertically
- (rcItem.Height() - rcButn.Height())>>1 );
- int iButton = pmd->iButton;
-
- //TRACE1("text=%s ",text);TRACE2("on draw: id=%d iButton=%d\n",lpds->itemID,iButton);
- if (iButton >= 0)
- {
-
- // this item has a button!
- bHaveButn = TRUE;
-
- // compute point to start drawing
- CSize sz = rcButn.Size() - m_szButton;
- sz.cx >>= 1;
- sz.cy >>= 1;
- CPoint p(rcButn.TopLeft() + sz);
-
- // draw disabled or normal
- if (!bDisabled)
- {
- // normal: fill BG depending on state
- PLFillRect(dc, rcButn, GetSysColor(
- (bChecked && !bSelected) ? COLOR_3DLIGHT : COLOR_MENU));
-
- // draw pushed-in or popped-out edge
- if (bSelected || bChecked)
- {
- CRect rc2 = rcButn;
- dc.DrawEdge(rc2, bChecked ? BDR_SUNKENOUTER : BDR_RAISEDINNER,
- BF_RECT);
- }
- }
- // draw the button!
- DrawButton(dc, iButton, p, !bDisabled);
-
- } else
- {
- // no button: look for custom checked/unchecked bitmaps
- CMenuItemInfo info;
- info.fMask = MIIM_CHECKMARKS;
- GetMenuItemInfo((HMENU)lpds->hwndItem,
- lpds->itemID, MF_BYCOMMAND, &info);
- if (bChecked || info.hbmpUnchecked) {
- bHaveButn = Draw3DCheckmark(dc, rcButn, bSelected,
- bChecked ? info.hbmpChecked : info.hbmpUnchecked);
-
- }
- }
-
- // Done with button, now paint text. First do background if needed.
- int cxButn = m_szButton.cx; // width of button
- COLORREF colorBG = GetSysColor(bSelected ? COLOR_HIGHLIGHT : COLOR_MENU);
- if (bSelected || lpds->itemAction==ODA_SELECT)
- {
- // selected or selection state changed: paint text background
- CRect rcBG = rcItem; // whole rectangle
- if (bHaveButn) // if there's a button:
- rcBG.left += cxButn + CXGAP; // don't paint over it!
- PLFillRect(dc, rcBG, colorBG); // paint it!
- }
-
- // compute text rectangle and colors
- CRect rcText = rcItem; // start w/whole item
- rcText.left += cxButn + CXGAP + CXTEXTMARGIN; // left margin
- rcText.right -= cxButn; // right margin
- dc.SetBkMode(TRANSPARENT); // paint transparent text
- COLORREF colorText = GetSysColor(bDisabled ? COLOR_GRAYTEXT :
- bSelected ? COLOR_HIGHLIGHTTEXT : COLOR_MENUTEXT);
-
- // Now paint menu item text. No need to select font,
- // because windows sets it up before sending WM_DRAWITEM
- //
- if (bDisabled && (!bSelected || colorText == colorBG))
- {
- // disabled: draw hilite text shifted southeast 1 pixel for embossed
- // look. Don't do it if item is selected, tho--unless text color same
- // as menu highlight color. Got it?
- //
- DrawMenuText(dc, rcText + CPoint(1,1), text, GetSysColor(COLOR_3DHILIGHT));
- }
- DrawMenuText(dc, rcText, text, colorText); // finally!
- }
- dc.Detach();
-
- return TRUE; // handled
- }
-
-
- //////////////////
- // Handle WM_INITMENUPOPUP on behalf of frame.
- //
- void CCoolMenuManager::OnInitMenuPopup(CMenu* pMenu, UINT nIndex, BOOL bSysMenu)
- {
- ConvertMenu(pMenu, nIndex, bSysMenu, TRUE);
- }
-
- //////////////////
- // Handle WM_MENUSELECT: check for menu closed
- //
- void CCoolMenuManager::OnMenuSelect(UINT nItemID, UINT nFlags, HMENU hSysMenu)
- {
- if (hSysMenu==NULL && nFlags==0xFFFF) {
- // Windows has closed the menu: restore all menus to original state
- while (!m_menuList.IsEmpty()) {
- ConvertMenu(CMenu::FromHandle((HMENU)m_menuList.RemoveHead()),
- 0, FALSE, FALSE);
- }
- }
- }
-
- //////////////////
- // This rather gnarly function is used both to convert the menu from strings to
- // owner-draw and vice versa. In either case, it also appends automagic
- // accelerator key names to the menu items, if m_bAutoAccel is TRUE.
- //
- void CCoolMenuManager::ConvertMenu(CMenu* pMenu,
- UINT nIndex, BOOL bSysMenu, BOOL bShowButtons)
- {
- ASSERT_VALID(pMenu);
-
- CString sItemName;
-
- UINT nItem = pMenu->GetMenuItemCount();
- for (UINT i = 0; i < nItem; i++) // loop over each item in menu
- {
- // get menu item info
- char itemname[256];
- CMenuItemInfo info;
- info.fMask = MIIM_SUBMENU | MIIM_DATA | MIIM_ID | MIIM_TYPE;
- info.dwTypeData = itemname;
- info.cch = sizeof(itemname);
- ::GetMenuItemInfo(*pMenu, i, TRUE, &info);
- CMyItemData* pmd = (CMyItemData*)info.dwItemData;
-
- if (pmd && !pmd->IsMyItemData())
- {
- TRACE0(_T("CCoolMenuManager: ignoring foreign owner-draw item\n"));
- continue; // owner-draw menu item isn't mine--leave it alone
- }
-
- if (bSysMenu && info.wID >= 0xF000)
- {
- TRACE0(_T("CCoolMenuManager: ignoring sys menu item\n"));
- continue; // don't do for system menu commands
- }
-
- // now that I have the info, I will modify it
- info.fMask = 0; // assume nothing to change
-
- if (bShowButtons)
- {
-
- // I'm showing buttons: convert to owner-draw
-
- if (!(info.fType & MFT_OWNERDRAW))
- {
- // If not already owner-draw, make it so. NOTE: If app calls
- // pCmdUI->SetText to change the text of a menu item, MFC will
- // turn the item to MFT_STRING. So I must set it back to
- // MFT_OWNERDRAW again. In this case, the menu item data (pmd)
- // will still be there.
- //
- info.fType |= MFT_OWNERDRAW;
- info.fMask |= MIIM_TYPE;
- if (!pmd)
- { // if no item data:
- pmd = new CMyItemData; // create one
- ASSERT(pmd); // (I hope)
- m_menuItems.AddTail(pmd);
-
- pmd->fType = info.fType; // handy when drawing
- pmd->iButton=m_pToolBar->CommandToIndex(info.wID);
-
-
- //TRACE2(_T("new wId=%d %s \t"), info.wID, info.dwTypeData); TRACE1("nin=%d\n",++nin);
- info.dwItemData = (DWORD)pmd; // set in menu item data
- info.fMask |= MIIM_DATA; // set item data
- }
- pmd->text = info.dwTypeData; // copy menu item string
- }
-
- // now add the menu to list of "converted" menus
- HMENU hmenu = pMenu->GetSafeHmenu();
- ASSERT(hmenu);
- if (!m_menuList.Find(hmenu))
- m_menuList.AddHead(hmenu);
-
-
- } else // !bShowButtons
- {
-
- // no buttons -- I'm converting to strings
-
- if (info.fType & MFT_OWNERDRAW)
- { // if ownerdraw:
- info.fType &= ~MFT_OWNERDRAW; // turn it off
- info.fMask |= MIIM_TYPE; // change item type
- ASSERT(pmd); // sanity check
- sItemName = pmd->text; // save name before deleting pmd
- } else // otherwise:
- sItemName = info.dwTypeData; // use name from MENUITEMINFO
-
- if (pmd)
- {
- // NOTE: pmd (item data) could still be left hanging around even
- // if MFT_OWNERDRAW is not set, in case mentioned above where app
- // calls pCmdUI->SetText to set text of item and MFC sets the type
- // to MFT_STRING.
- //
- info.dwItemData = NULL; // item data is NULL
- info.fMask |= MIIM_DATA; // change it
- POSITION pos=m_menuItems.Find(pmd);
- if (pos!=NULL)
- m_menuItems.RemoveAt(pos);
- delete pmd; // and item data too
- //TRACE2(_T("delete wId=%d %s \t"), info.wID, sItemName); TRACE1("nin=%d\n",--nin);
- }
-
-
- if (info.fMask & MIIM_TYPE)
- {
- // if setting name, copy name from CString to buffer and set cch
- strncpy(itemname, sItemName, sizeof(itemname));
- info.dwTypeData = itemname;
- info.cch = sItemName.GetLength();
- }
- }
-
- // if after all the above, there is anything to change, change it
- if (info.fMask)
- {
- //TRACE2(_T("Converting '%s' to %s\n"), itemname, (info.fType & MFT_OWNERDRAW) ? _T("OWNERDRAW") : _T("STRING"));
- SetMenuItemInfo(*pMenu, i, TRUE, &info);
- }
- }
- }
-
-
-
-
- //////////////////
- // Virtual CSubclassWnd window proc. All messages come here before frame
- // window. Isn't it cool? Just like in the old days!
- //
- LRESULT CCoolMenuManager::WindowProc(UINT msg, WPARAM wp, LPARAM lp)
- {
- switch(msg)
- {
-
- case WM_MEASUREITEM:
- if (OnMeasureItem((MEASUREITEMSTRUCT*)lp))
- return TRUE; // handled
- break;
-
- case WM_DRAWITEM:
- if (OnDrawItem((DRAWITEMSTRUCT*)lp))
- return TRUE; // handled
- break;
-
- case WM_INITMENUPOPUP:
- // Very important: must let frame window handle it first!
- // Because if someone calls CCmdUI::SetText, MFC will change item to
- // MFT_STRING, so I must change back to MFT_OWNERDRAW.
- //
- CSubclassWnd::WindowProc(msg, wp, lp);
- OnInitMenuPopup(CMenu::FromHandle((HMENU)wp),
- (UINT)LOWORD(lp), (BOOL)HIWORD(lp));
- return 0;
-
- case WM_MENUSELECT:
- OnMenuSelect((UINT)LOWORD(wp), (UINT)HIWORD(wp), (HMENU)lp);
- break;
-
- case WM_NOTIFY:
- OnNotify(msg, wp, lp);
- break;
- case WM_COMMAND:
- {
- UINT nId = LOWORD(wp);// GET_WM_COMMAND_ID(wParam,lParam);
- switch ( nId )
- {
- case ID_FILEDROPDOWN: //-->> unused now
- OnFiledropdown(nId);
- break;
- }
- break;
- }
- }
- return CSubclassWnd::WindowProc(msg, wp, lp);
- }
-
-
-
- BOOL CCoolMenuManager::OnNotify(UINT msg, WPARAM wParam, LPARAM lParam)
- {
- LPNMHDR lpnm = (LPNMHDR)lParam;
-
- switch(lpnm->code)
- {
- case TBN_DROPDOWN:
- {
-
- RECT rc;
- LPNMTOOLBAR lpnmTB =(LPNMTOOLBAR)lParam;
-
- CMyDropData* pdd;
- ASSERT(pdd);
- if ( !m_dropButns.Lookup(lpnmTB->iItem, (void *&)pdd)
- || !pdd->IsMyDropData())
- {
- // TRACE2("idBut=%d idMenu=%d\n",lpnmTB->iItem, pdd->idMenu);
- return FALSE; // not handled by me
- }
-
- SendMessage(lpnmTB->hdr.hwndFrom, TB_GETRECT,
- (WPARAM)lpnmTB->iItem, (LPARAM)&rc);
- MapWindowPoints(lpnmTB->hdr.hwndFrom, HWND_DESKTOP, (LPPOINT)&rc, 2);
-
- CMenu bar;
- if (bar.LoadMenu(pdd->idMenu))
- {
- CMenu& popup = *bar.GetSubMenu(0);
- ASSERT(popup.m_hMenu != NULL);
- popup.TrackPopupMenu(pdd->uFlags, rc.left, rc.bottom, AfxGetMainWnd());
- }
-
-
- /*
-
- TPMPARAMS tpm;
- tpm.cbSize = sizeof(TPMPARAMS);
- tpm.rcExclude = rc;
- hMenuLoaded = LoadMenu(g_hinst, MAKEINTRESOURCE(IDR_POPUP));
- hPopupMenu = GetSubMenu(LoadMenu(g_hinst,
- MAKEINTRESOURCE(IDR_POPUP)),0);
- TrackPopupMenuEx(hPopupMenu,
- TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
- rc.left, rc.bottom, g_hwndMain, &tpm);
- DestroyMenu(hMenuLoaded);
- */
-
- }
-
- return (FALSE);
- }
-
- return FALSE;
- }
-
-
-
-
- //-------------------------------------------------------------------------------
- // ╧ε Ωφε∩Ωσ popup menu
- // Unused now
- void CCoolMenuManager::OnFiledropdown(UINT nIdButn)
- {
- UINT nIdMenu;
- if (nIdButn == ID_FILEDROPDOWN)
- nIdMenu = IDR_FILEDROPDOWN;
- else return;
- CRect rc;
- m_pToolBar->GetToolBarCtrl().GetRect(nIdButn, &rc);
-
-
- CPoint point(rc.left, rc.bottom+3);
- m_pFrame->ClientToScreen(&point);
- if (!m_pToolBar->SendMessage(TB_ISBUTTONCHECKED,(WPARAM)nIdButn,0))
- {
- CMenu bar;
- if (bar.LoadMenu(nIdMenu))
- {
- m_pToolBar->SendMessage(TB_CHECKBUTTON,(WPARAM)nIdButn,(LPARAM)MAKELONG( TRUE,0));
- CMenu& popup = *bar.GetSubMenu(0);
- ASSERT(popup.m_hMenu != NULL);
-
- popup.TrackPopupMenu(TPM_RIGHTBUTTON, point.x, point.y, AfxGetMainWnd());
- }
- }
- m_pToolBar->SendMessage(TB_CHECKBUTTON,(WPARAM)nIdButn,(LPARAM)MAKELONG(FALSE,0));
- }
-